# encoding: utf-8
import requests, datetime, json, urllib, traceback, re, time
from flask_restplus import Resource
from app.extensions.api import Namespace
from app.modules.common.utils import DbCommit, checkToken
from app.modules.thread.thread import AddThreadTask
from . import parameters
from app.modules.apps.models import AppInfo
from app.modules.common.schemas import BaseSchema
from app.extensions import log
from app.modules.zones.models import ZoneInfo
from app.modules.entrance.models import EntranceInfo
from config import BaseConfig
from app.modules.log.resources import insertLog

api = Namespace('switch', description = "切换应用状态")  # pylint: disable=invalid-name


@api.route('/')
class Switch(Resource):
    @api.parameters(parameters.SwitchParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        切换应用
        :param args:
        :return:
        """
        _env_name = args['env_name']
        _zone_code = args['zone_code']
        _entrance_types = args['entrance_types']
        _status = args['status']
        _app_name = args['app_name']

        if _entrance_types is None and _app_name is None:
            _msg = "参数entrance_types和app_name不能同时为空."
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _zone = ZoneInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code).first()
        if _zone is None:
            _msg = "环境 %s 区域 %s 不存在." % (_env_name, _zone_code)
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}
        return doSwitch(_env_name, _zone_code, _entrance_types, _status, _app_name)


def doSwitch(_env_name, _zone_code, _entrance_types, _status, _app_name):
    _group = None
    if _status == "GA":
        _group = "A"
    if _status == "GB":
        _group = "B"

    _zone = ZoneInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code).first()
    _resources = []
    # 优先app_name
    if _app_name is not None:
        for _app in AppInfo.query.filter_by(env_name = _env_name, app_name = _app_name,
                                            zone_code = _zone_code, is_resource = '0').all():
            _r = validate(_app.expect_status, _app.current_status, _status, _app.is_overtime)
            if not _r['success']:
                return _r
            if 'jmx' == _app.entrance_type:
                _entrance_info = EntranceInfo.query.filter_by(id = _app.entrance_id).first()
                _resources.append(
                    '%s://%s:%s' % (_entrance_info.prefix, _app.host, _app.jmx_port))
                _app.expect_status = _status
                _app.current_status = 'DOING'
                _app.error_desc = None
                _app.cloudlink_status = None
                _app.dubbo_status = None
                _app.update_time = datetime.datetime.now()
                _app.is_overtime = '1'
            elif 'hosts' == _app.entrance_type:
                _entrance_info = EntranceInfo.query.filter_by(id = _app.entrance_id).first()
                # host类型操作哪个组传哪个组的数据
                if _zone_code in BaseConfig.HOSTS_GROUP_ZONE:
                    if _group is None or _group == _app.group:
                        _h_resource = '%s://%s:%s%s' % (
                            _entrance_info.prefix, _app.host, _app.agent_port, _entrance_info.suffix)
                        if _h_resource not in _resources:
                            _resources.append(_h_resource)
                        _app.expect_status = _status
                        _app.current_status = 'DOING'
                        _app.error_desc = None
                        _app.update_time = datetime.datetime.now()
                        _app.is_overtime = '1'
                else:
                    _h_resource = '%s://%s:%s%s' % (
                        _entrance_info.prefix, _app.host, _app.agent_port, _entrance_info.suffix)
                    if _h_resource not in _resources:
                        _resources.append(_h_resource)
                    _app.expect_status = _status
                    _app.current_status = 'DOING'
                    _app.error_desc = None
                    _app.update_time = datetime.datetime.now()
                    _app.is_overtime = '1'
    else:
        if _entrance_types is not None:
            for _entrance_info in EntranceInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code).filter(
                    EntranceInfo.type.in_(str(_entrance_types).split(','))).all():
                _r = validate(_entrance_info.expect_status, _entrance_info.current_status, _status,
                              _entrance_info.is_overtime)
                if not _r['success']:
                    return _r

                if 'jmx' == _entrance_info.type:
                    for _app in AppInfo.query.filter_by(entrance_id = _entrance_info.id, is_resource = '0').all():
                        _resources.append(
                            '%s://%s:%s' % (_entrance_info.prefix, _app.host, _app.jmx_port))
                        _app.expect_status = _status
                        _app.current_status = 'DOING'
                        _app.error_desc = None
                        _app.cloudlink_status = None
                        _app.dubbo_status = None
                        _app.update_time = datetime.datetime.now()
                        _app.is_overtime = '1'
                elif 'elb' == _entrance_info.type:
                    _resources.append('%s://%s:%s@%s%s' % (
                        _entrance_info.prefix, str(_entrance_info.user).split(':')[0],
                        urllib.quote_plus(str(_entrance_info.user).split(':')[1]), _entrance_info.hosts,
                        _entrance_info.suffix))
                elif 'uschedule' == _entrance_info.type:
                    _resources.append(
                        '%s://%s%s' % (_entrance_info.prefix, _entrance_info.hosts, _entrance_info.suffix))
                elif 'haproxy' == _entrance_info.type:
                    _resources.append(
                        '%s://%s%s' % (_entrance_info.prefix, _entrance_info.hosts, _entrance_info.suffix))
                elif 'hosts' == _entrance_info.type:
                    _query = AppInfo.query.filter_by(entrance_id = _entrance_info.id, is_resource = '0')
                    if _zone_code in BaseConfig.HOSTS_GROUP_ZONE and _group is not None:
                        _query = _query.filter_by(group = _group)
                    for _app in _query.all():
                        _h_resource = '%s://%s:%s%s' % (
                            _entrance_info.prefix, _app.host, _app.agent_port, _entrance_info.suffix)
                        if _h_resource not in _resources:
                            _resources.append(_h_resource)
                        _app.expect_status = _status
                        _app.current_status = 'DOING'
                        _app.error_desc = None
                        _app.update_time = datetime.datetime.now()
                        _app.is_overtime = '1'
                _entrance_info.expect_status = _status
                _entrance_info.current_status = 'DOING'
                _entrance_info.error_desc = None
                _entrance_info.update_time = datetime.datetime.now()
                _entrance_info.is_overtime = '1'

        _zone.current_status = 'DOING'
        _zone.expect_status = _status
        _zone.update_time = datetime.datetime.now()

    _data = {"mode": _status, "tasks": _resources, "env": getSwitchEnvParam(_env_name, _zone_code)}
    log.info("============== do switch env_name=%s,zone_code=%s,entrance_types=%s,status=%s . %s" % (
        _env_name, _zone_code, _entrance_types, _status, json.dumps(_data)))
    try:
        _rtn = requests.post(url = '%s/api/v1/switcher' % _zone.barrier_url, json = _data, timeout = 600).json()
    except BaseException:
        _msg = "调用环境 %s 区域 %s ubarrier异常.错误信息:%s" % (_env_name, _zone_code, traceback.format_exc())
        log.error("============== %s ==============" % _msg)
        return {'success': False, 'msg': _msg}
    log.info(
        "==============切换:env_name=%s,zone_code=%s,entrance_types=%s,status=%s.返回: %s ==============" % (
            _env_name, _zone_code, _entrance_types, _status, _rtn))
    # 启动定时任务查询切换状态
    # addSwitchList('%s_%s' % (_env_name, _zone_code))
    DbCommit()
    return handleStatus(_env_name, _zone_code, 'do', _rtn)


@api.route('/switchTask')
class SwitchTask(Resource):
    @api.parameters(parameters.SwitchParameters())
    @checkToken
    def get(self, args, **kwargs):
        """
        获取切换用资源列表
        :param args:
        :return:
        """
        _env_name = args['env_name']
        _zone_code = args['zone_code']
        _entrance_types = args['entrance_types']
        _status = args['status']
        _app_name = args['app_name']

        _group = None
        if _status == "GA":
            _group = "A"
        if _status == "GB":
            _group = "B"

        if _entrance_types is None and _app_name is None:
            _msg = "参数entrance_types和app_name不能同时为空."
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _zone = ZoneInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code).first()
        if _zone is None:
            _msg = "环境 %s 区域 %s 不存在." % (_env_name, _zone_code)
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _resources = []
        # 优先app_name
        if _app_name is not None:
            for _app in AppInfo.query.filter_by(env_name = _env_name, app_name = _app_name,
                                                zone_code = _zone_code, is_resource = '0').all():
                _r = validate(_app.expect_status, _app.current_status, _status, _app.is_overtime)
                if not _r['success']:
                    return _r
                if 'jmx' == _app.entrance_type:
                    _entrance_info = EntranceInfo.query.filter_by(id = _app.entrance_id).first()
                    _resources.append(
                        '%s://%s:%s' % (_entrance_info.prefix, _app.host, _app.jmx_port))
                elif 'hosts' == _app.entrance_type:
                    _entrance_info = EntranceInfo.query.filter_by(id = _app.entrance_id).first()
                    # host类型操作哪个组传哪个组的数据
                    if _zone_code in BaseConfig.HOSTS_GROUP_ZONE:
                        if _group is None or _group == _app.group:
                            _h_resource = '%s://%s:%s%s' % (
                                _entrance_info.prefix, _app.host, _app.agent_port, _entrance_info.suffix)
                            if _h_resource not in _resources:
                                _resources.append(_h_resource)
                    else:
                        _h_resource = '%s://%s:%s%s' % (
                            _entrance_info.prefix, _app.host, _app.agent_port, _entrance_info.suffix)
                        if _h_resource not in _resources:
                            _resources.append(_h_resource)
        else:
            if _entrance_types is not None:
                for _entrance_info in EntranceInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code).filter(
                        EntranceInfo.type.in_(str(_entrance_types).split(','))).all():
                    _r = validate(_entrance_info.expect_status, _entrance_info.current_status, _status,
                                  _entrance_info.is_overtime)
                    if not _r['success']:
                        return _r

                    if 'jmx' == _entrance_info.type:
                        for _app in AppInfo.query.filter_by(entrance_id = _entrance_info.id, is_resource = '0').all():
                            _resources.append(
                                '%s://%s:%s' % (_entrance_info.prefix, _app.host, _app.jmx_port))
                    elif 'elb' == _entrance_info.type:
                        _resources.append('%s://%s:%s@%s%s' % (
                            _entrance_info.prefix, str(_entrance_info.user).split(':')[0],
                            urllib.quote_plus(str(_entrance_info.user).split(':')[1]), _entrance_info.hosts,
                            _entrance_info.suffix))
                    elif 'uschedule' == _entrance_info.type:
                        _resources.append(
                            '%s://%s%s' % (_entrance_info.prefix, _entrance_info.hosts, _entrance_info.suffix))
                    elif 'haproxy' == _entrance_info.type:
                        _resources.append(
                            '%s://%s%s' % (_entrance_info.prefix, _entrance_info.hosts, _entrance_info.suffix))
                    elif 'hosts' == _entrance_info.type:
                        _query = AppInfo.query.filter_by(entrance_id = _entrance_info.id, is_resource = '0')
                        if _zone_code in BaseConfig.HOSTS_GROUP_ZONE and _group is not None:
                            _query = _query.filter_by(group = _group)
                        for _app in _query.all():
                            _h_resource = '%s://%s:%s%s' % (
                                _entrance_info.prefix, _app.host, _app.agent_port, _entrance_info.suffix)
                            if _h_resource not in _resources:
                                _resources.append(_h_resource)

        _data = {"mode": _status, "tasks": _resources, "env": getSwitchEnvParam(_env_name, _zone_code)}
        return _data


@api.route('/check')
class Check(Resource):
    @api.parameters(parameters.CheckParameters())
    @api.response(BaseSchema(many = False))
    @checkToken
    def get(self, args, **kwargs):
        """
        校验资源
        :param args:
        :return:
        """
        _env_name = args['env_name']
        _zone_code = args['zone_code']
        _zone = ZoneInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code).first()
        if _zone is None:
            _msg = "环境 %s 区域 %s 不存在." % (_env_name, _zone_code)
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        insertLog(log = '===============开始校验==============', zone_code = _zone_code, env_name = _env_name)
        _r = doCheck(_env_name, _zone_code)
        if _r['data'] == 'OUT_OF_SERVICE':
            insertLog(log = '资源校验失败。。。。', color = 'red', zone_code = _zone_code, env_name = _env_name, show_error = "0")
            insertLog(log = '===============校验失败==============', br_count = 3, color = 'red', zone_code = _zone_code,
                      env_name = _env_name)
        else:
            insertLog(log = '===============校验成功==============', br_count = 3, zone_code = _zone_code,
                      env_name = _env_name)
        return _r


@api.route('/checkTask')
class CheckTask(Resource):
    @api.parameters(parameters.CheckParameters())
    @checkToken
    def get(self, args, **kwargs):
        """
        获取校验资源task
        :param args:
        :return:
        """
        env_name = args['env_name']
        zone_code = args['zone_code']
        _zone = ZoneInfo.query.filter_by(env_name = env_name, zone_code = zone_code).first()
        if _zone is None:
            _msg = "环境 %s 区域 %s 不存在." % (env_name, zone_code)
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        _resources = []
        for _entrance_info in EntranceInfo.query.filter_by(env_name = env_name, zone_code = zone_code).all():
            if 'jmx' == _entrance_info.type:
                for _app in AppInfo.query.filter_by(entrance_id = _entrance_info.id, is_resource = '0').all():
                    _resources.append(
                        '%s://%s:%s' % (_entrance_info.prefix, _app.host, _app.jmx_port))
            elif 'elb' == _entrance_info.type:
                _resources.append('%s://%s:%s@%s%s' % (
                    _entrance_info.prefix, str(_entrance_info.user).split(':')[0],
                    urllib.quote_plus(str(_entrance_info.user).split(':')[1]), _entrance_info.hosts,
                    _entrance_info.suffix))
            elif 'uschedule' == _entrance_info.type:
                _resources.append(
                    '%s://%s%s' % (_entrance_info.prefix, _entrance_info.hosts, _entrance_info.suffix))
            elif 'haproxy' == _entrance_info.type:
                _resources.append(
                    '%s://%s%s' % (_entrance_info.prefix, _entrance_info.hosts, _entrance_info.suffix))
            elif 'hosts' == _entrance_info.type:
                _query = AppInfo.query.filter_by(entrance_id = _entrance_info.id, is_resource = '0')
                for _app in _query.all():
                    _h_resource = '%s://%s:%s%s' % (
                        _entrance_info.prefix, _app.host, _app.agent_port, _entrance_info.suffix)
                    if _h_resource not in _resources:
                        _resources.append(_h_resource)
        _data = {"tasks": _resources}
        return _data


def doCheck(env_name, zone_code):
    """
    资源检验
    :return:
    """
    _zone = ZoneInfo.query.filter_by(env_name = env_name, zone_code = zone_code).first()

    _resources = []
    for _entrance_info in EntranceInfo.query.filter_by(env_name = env_name, zone_code = zone_code).all():
        # if _entrance_info.current_status == 'DOING' and _entrance_info.is_overtime == '1':
        #     _msg = "环境 %s 区域 %s 入口 %s 正在切换中,请稍后......" % (env_name, zone_code, _entrance_info.type)
        #     log.error("============== %s ==============" % _msg)
        #     return {'success': False, 'msg': _msg}

        if 'jmx' == _entrance_info.type:
            for _app in AppInfo.query.filter_by(entrance_id = _entrance_info.id, is_resource = '0').all():
                _resources.append(
                    '%s://%s:%s' % (_entrance_info.prefix, _app.host, _app.jmx_port))
                _app.current_status = 'DOING'
                _app.expect_status = 'READY'
                _app.error_desc = None
                _app.update_time = datetime.datetime.now()
                _app.is_overtime = '1'
        elif 'elb' == _entrance_info.type:
            _resources.append('%s://%s:%s@%s%s' % (
                _entrance_info.prefix, str(_entrance_info.user).split(':')[0],
                urllib.quote_plus(str(_entrance_info.user).split(':')[1]), _entrance_info.hosts,
                _entrance_info.suffix))
        elif 'uschedule' == _entrance_info.type:
            _resources.append(
                '%s://%s%s' % (_entrance_info.prefix, _entrance_info.hosts, _entrance_info.suffix))
        elif 'haproxy' == _entrance_info.type:
            _resources.append(
                '%s://%s%s' % (_entrance_info.prefix, _entrance_info.hosts, _entrance_info.suffix))
        elif 'hosts' == _entrance_info.type:
            _query = AppInfo.query.filter_by(entrance_id = _entrance_info.id, is_resource = '0')
            for _app in _query.all():
                _h_resource = '%s://%s:%s%s' % (
                    _entrance_info.prefix, _app.host, _app.agent_port, _entrance_info.suffix)
                if _h_resource not in _resources:
                    _resources.append(_h_resource)
                _app.current_status = 'DOING'
                _app.expect_status = 'READY'
                _app.error_desc = None
                _app.update_time = datetime.datetime.now()
                _app.is_overtime = '1'
        _entrance_info.current_status = 'DOING'
        _entrance_info.expect_status = 'READY'
        _entrance_info.error_desc = None
        _entrance_info.update_time = datetime.datetime.now()
        _entrance_info.is_overtime = '1'
    _zone.current_status = 'DOING'
    _zone.expect_status = 'READY'
    _zone.check_status = None
    _zone.update_time = datetime.datetime.now()
    _data = {"tasks": _resources}
    log.info("============== do check env_name=%s,zone_code=%s. %s" % (env_name, zone_code, json.dumps(_data)))
    try:
        _rtn = requests.post(url = '%s/api/v1/switcher/check' % _zone.barrier_url, json = _data, timeout = 600).json()
    except BaseException:
        _msg = "调用环境 %s 区域 %s ubarrier异常.错误信息:%s" % (env_name, zone_code, traceback.format_exc())
        log.error("============== %s ==============" % _msg)
        return {'success': False, 'msg': _msg}
    log.info(
        "==============校验:env_name=%s,zone_code=%s.返回: %s ==============" % (env_name, zone_code, _rtn))
    # 启动定时任务查询切换状态 调用接口后直接返回状态
    # addSwitchList('%s_%s' % (env_name, zone_code))
    DbCommit()
    return handleStatus(env_name, zone_code, 'check', _rtn)


def handleStatus(_env_name, _zone_code, _type, _rtn):
    """
    处理调用ubarrier接口返回的状态
    :return:
    """
    _zone = ZoneInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code).first()
    if _zone is None:
        _msg = "环境 %s 区域 %s 不存在." % (_env_name, _zone_code)
        log.error("============== %s ==============" % _msg)
        return {'success': False, 'msg': _msg}

    _status = None

    for _obj in _rtn:
        if str(_obj).startswith('elb') or str(_obj).startswith('uschedule') or str(_obj).startswith(
                'haproxy'):
            _hosts = re.sub("([\\s\\S]*)(://)([\\s\\S]+?)(/)([\\s\\S]+)", "\\3", str(_obj))
            _entranct = EntranceInfo.query.filter_by(zone_code = _zone_code, env_name = _env_name,
                                                     hosts = _hosts).first()
            if _entranct is not None:
                _entranct.current_status = _rtn[_obj]['status']
                _status = getZoneStatus(_status, _rtn[_obj]['status'])
                _entranct.is_overtime = getIsOvertime(_entranct.current_status, _entranct.update_time)
                # _entranct.update_time = datetime.datetime.now()
                if 'error' in _rtn[_obj]:
                    _entranct.error_desc = _rtn[_obj]['error']
        elif str(_obj).startswith('jmx'):
            _hosts = str(_obj).split('//')[1].split(':')
            _app = AppInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code, host = _hosts[0],
                                           jmx_port = _hosts[1], is_resource = '0').first()
            if _app is not None:
                _app.current_status = _rtn[_obj]['status']
                _status = getZoneStatus(_status, _rtn[_obj]['status'])
                _app.is_overtime = getIsOvertime(_app.current_status, _app.update_time)
                # _app.update_time = datetime.datetime.now()
                if 'error' in _rtn[_obj]:
                    _app.error_desc = _rtn[_obj]['error']
                if 'cloudlink' in _rtn[_obj]:
                    _app.cloudlink_status = _rtn[_obj]['cloudlink']['status']
                if 'dubbo' in _rtn[_obj]:
                    _app.dubbo_status = _rtn[_obj]['dubbo']['status']
        elif str(_obj).startswith('hosts'):
            _entranct = EntranceInfo.query.filter_by(zone_code = _zone_code, env_name = _env_name,
                                                     type = "hosts").first()
            if _entranct is None:
                pass
            _hosts = str(_obj).replace(_entranct.suffix, '').split('//')[1].split(':')

            for _app in AppInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code, host = _hosts[0],
                                                agent_port = _hosts[1], is_resource = '0').all():
                _app.current_status = _rtn[_obj]['status']
                _status = getZoneStatus(_status, _rtn[_obj]['status'])
                _app.is_overtime = getIsOvertime(_app.current_status, _app.update_time)
                # _app.update_time = datetime.datetime.now()
                if 'error' in _rtn[_obj]:
                    _app.error_desc = _rtn[_obj]['error']

    _zone.current_status = _status
    if _type == 'check':
        _zone.check_status = 'READY'

    DbCommit()

    # 修改jmx入口状态
    updateEntranceStatus(_env_name, _zone_code, 'jmx')
    # 修改hosts入口状态
    updateEntranceStatus(_env_name, _zone_code, 'hosts')
    return {'success': True, 'msg': '', 'data': _status}


def getZoneStatus(_rtn, status):
    if _rtn is None:
        return status
    else:
        if 'OUT_OF_SERVICE' == _rtn:
            return _rtn
        else:
            return status


def validate(_expect_status, _current_status, _status, is_overtime):
    """
    判断当前给定的入口或者应用是否可切换
    :param is_overtime:
    :param _expect_status:
    :param _current_status:
    :param _status:
    :return:
    """
    return {'success': True, 'msg': ''}


def getSwitchEnvParam(_env_name, _zone_code):
    """
    获取切换用的参数 env
    :return:
    """
    _ahosts = []
    _bhosts = []
    # haproxy
    for _ha in EntranceInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code, type = 'haproxy').all():
        _host = str(_ha.hosts).split(':')[0]
        if 'A' == _ha.group:
            if _host not in _ahosts:
                _ahosts.append(_host)
        elif 'B' == _ha.group:
            if _host not in _bhosts:
                _bhosts.append(_host)

    # app
    for _app in AppInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code).all():
        if 'A' == _app.group:
            if _app.host not in _ahosts:
                _ahosts.append(_app.host)
        elif 'B' == _app.group:
            if _app.host not in _bhosts:
                _bhosts.append(_app.host)

    return {'ahosts': _ahosts, 'bhosts': _bhosts}


def updateEntranceStatus(_env_name, _zone_code, _type):
    for _entranct in EntranceInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code, type = _type).all():
        _expect_status = _entranct.expect_status
        _group = None
        if 'GA' == _expect_status:
            _group = 'A'
        elif 'GB' == _expect_status:
            _group = 'B'
        _query = AppInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code,
                                         entrance_id = _entranct.id, is_resource = '0').filter(
            AppInfo.current_status != _expect_status)
        if _group is not None:
            _query = _query.filter_by(group = _group)

        _status = _expect_status
        _error = None
        for _app in _query.all():
            if _app.current_status == 'DOING':
                _status = 'DOING'
                _error = None
                break
            _status = 'OUT_OF_SERVICE'
            if _app.error_desc is not None:
                _error = _app.error_desc
        _entranct.current_status = _status
        _entranct.is_overtime = getIsOvertime(_entranct.current_status, _entranct.update_time)
        # _entranct.update_time = datetime.datetime.now()
        _entranct.error_desc = _error
    DbCommit()


def getIsOvertime(status, update_time):
    if status != 'DOING':
        return '1'
    now = datetime.datetime.now()
    if (now - update_time).seconds > BaseConfig.UBARRIER_OVER_TIME:
        return '0'
    else:
        return '1'


@api.route('/autoSwitch')
class AutoSwitch(Resource):
    @api.parameters(parameters.AutoSwitchParameters())
    @api.response(BaseSchema(many = False))
    def post(self, args):
        """
        一键切换应用状态
        :param args:
        :return:
        """
        _env_name = args['env_name']
        _zone_code = args['zone_code']
        _status = args['status']
        _group = args['group']

        _zone = ZoneInfo.query.filter_by(env_name = _env_name, zone_code = _zone_code).first()
        if _zone is None:
            _msg = "环境 %s 区域 %s 不存在." % (_env_name, _zone_code)
            log.error("============== %s ==============" % _msg)
            return {'success': False, 'msg': _msg}

        # 启动线程进行切换
        if _status == 'GNONE':
            AddThreadTask(autoGNONE, _env_name, _zone_code, _group)
        else:
            AddThreadTask(autoG, _env_name, _zone_code, _group, _status)

        return {'success': True, 'msg': ''}


def autoG(env_name, zone_code, group, status):
    """
    一键切换备用
    :param env_name:
    :param zone_code:
    :param group:
    :param status:
    :return:
    """
    insertLog(log = '===============%s组备用==============' % group, zone_code = zone_code, env_name = env_name,
              group = group)

    # 1、uSchedule取消A组任务{'success': False, 'msg': _msg}

    insertLog(log = 'uSchedule取消%s组任务。。。。' % group, zone_code = zone_code, env_name = env_name,
              entrance_types = 'uschedule', group = group)
    _rtn = doSwitch(env_name, zone_code, 'uschedule', status, None)
    log.info("app.modules.switch.resources.autoG  uschedule切换%s,返回:%s" % (status, _rtn))
    if not _rtn['success'] or _rtn['data'] == 'OUT_OF_SERVICE':
        log.error("app.modules.switch.resources.autoG  uschedule切换%s失败" % status)

        insertLog(log = 'uSchedule取消%s组任务失败。。。。' % group, color = 'red', zone_code = zone_code, env_name = env_name,
                  entrance_types = 'uschedule', group = group, show_error = "0")
        insertLog(log = '===============%s组备用失败==============' % group, br_count = 3, color = 'red',
                  zone_code = zone_code, env_name = env_name, group = group)
        return
    insertLog(log = 'uSchedule取消%s组任务成功。。。。' % group, color = 'green', zone_code = zone_code, env_name = env_name,
              entrance_types = 'uschedule', group = group)

    # 2、生产Haproxy禁A

    insertLog(log = '生产Haproxy禁%s组。。。。' % group, zone_code = zone_code, env_name = env_name,
              entrance_types = 'haproxy', group = group)
    _rtn = doSwitch(env_name, zone_code, 'haproxy', status, None)
    log.info("app.modules.switch.resources.autoG  haproxy切换%s,返回:%s" % (status, _rtn))
    if not _rtn['success'] or _rtn['data'] == 'OUT_OF_SERVICE':
        log.error("app.modules.switch.resources.autoG  haproxy切换%s失败" % status)
        insertLog(log = '生产Haproxy禁%s组失败。。。。' % group, color = 'red', zone_code = zone_code, env_name = env_name,
                  entrance_types = 'haproxy', group = group, show_error = "0")
        insertLog(log = '===============%s组备用失败==============' % group, br_count = 3, color = 'red',
                  zone_code = zone_code, env_name = env_name, group = group)
        return
    insertLog(log = '生产Haproxy禁%s组成功。。。。' % group, color = 'green', zone_code = zone_code, env_name = env_name,
              entrance_types = 'haproxy', group = group)

    # 3、A组php应用进入备用

    insertLog(log = '%s组php应用进入备用。。。。' % group, zone_code = zone_code, env_name = env_name,
              entrance_types = 'hosts', group = group)
    _rtn = doSwitch(env_name, zone_code, 'hosts', status, None)
    log.info("app.modules.switch.resources.autoG  hosts切换%s,返回:%s" % (status, _rtn))
    if not _rtn['success'] or _rtn['data'] == 'OUT_OF_SERVICE':
        log.error("app.modules.switch.resources.autoG  hosts切换%s失败" % status)
        insertLog(log = '%s组php应用进入备用失败。。。。' % group, color = 'red', zone_code = zone_code, env_name = env_name,
                  entrance_types = 'hosts', group = group, show_error = "0")
        insertLog(log = '===============%s组备用失败==============' % group, br_count = 3, color = 'red',
                  zone_code = zone_code, env_name = env_name, group = group)
        return
    insertLog(log = '%s组php应用进入备用成功。。。。' % group, color = 'green', zone_code = zone_code, env_name = env_name,
              entrance_types = 'hosts', group = group)

    # 4、A组Java应用进入备用

    insertLog(log = '%s组Java应用进入备用。。。。' % group, zone_code = zone_code, env_name = env_name,
              entrance_types = 'jmx', group = group)
    _rtn = doSwitch(env_name, zone_code, 'jmx', status, None)
    log.info("app.modules.switch.resources.autoG  jmx切换%s,返回:%s" % (status, _rtn))
    if not _rtn['success'] or _rtn['data'] == 'OUT_OF_SERVICE':
        log.error("app.modules.switch.resources.autoG  jmx切换%s失败" % status)
        insertLog(log = '%s组Java应用进入备用失败。。。。' % group, color = 'red', zone_code = zone_code, env_name = env_name,
                  entrance_types = 'jmx', group = group, show_error = "0")
        insertLog(log = '===============%s组备用失败==============' % group, br_count = 3, color = 'red',
                  zone_code = zone_code, env_name = env_name, group = group)
        return
    insertLog(log = '%s组Java应用进入备用成功。。。。' % group, color = 'green', zone_code = zone_code, env_name = env_name,
              entrance_types = 'jmx', group = group)
    insertLog(log = '===============%s组备用成功==============' % group, br_count = 3, color = 'green',
              zone_code = zone_code, env_name = env_name, entrance_types = 'uschedule', group = group)

    # 5、等待10分钟

    insertLog(log = '请等待%s分钟后,检查系统是否切换完成。。。当前时间:%s' % (
        BaseConfig.AUTO_SWITCH_WAIT_TIME, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')), br_count = 3,
              zone_code = zone_code, env_name = env_name, group = group)
    time.sleep(BaseConfig.AUTO_SWITCH_WAIT_TIME * 60)
    insertLog(log = '%s分钟已到，请检查系统是否切换完成。。。当前时间:%s' % (
        BaseConfig.AUTO_SWITCH_WAIT_TIME, datetime.datetime.now().strftime('%Y-%m-%d %H:%M:%S')), br_count = 3,
              zone_code = zone_code, env_name = env_name, group = group)
    pass


def autoGNONE(env_name, zone_code, group):
    """
    一键取消备用
    :param env_name:
    :param zone_code:
    :param group:
    :return:
    """
    insertLog(log = '===============%s组取消备用==============' % group, zone_code = zone_code, env_name = env_name,
              group = group)

    # 1、A组Java应用上线

    insertLog(log = '%s组Java应用上线。。。。' % group, zone_code = zone_code, env_name = env_name,
              entrance_types = 'jmx', group = group)
    _rtn = doSwitch(env_name, zone_code, 'jmx', 'GNONE', None)
    log.info("app.modules.switch.resources.autoGNONE  %s组jmx切换GNONE,返回:%s" % (group, _rtn))
    if not _rtn['success'] or _rtn['data'] == 'OUT_OF_SERVICE':
        log.error("app.modules.switch.resources.autoGNONE  %s组jmx切换GNONE失败" % group)
        insertLog(log = '%s组Java应用上线失败。。。。' % group, color = 'red', zone_code = zone_code, env_name = env_name,
                  entrance_types = 'jmx', group = group, show_error = "0")
        insertLog(log = '===============%s组取消备用失败==============' % group, br_count = 3, color = 'red',
                  zone_code = zone_code, env_name = env_name, group = group)
        return
    insertLog(log = '%s组Java应用上线成功。。。。' % group, color = 'green', zone_code = zone_code, env_name = env_name,
              entrance_types = 'jmx', group = group)

    # 2、A组php应用取消备用

    insertLog(log = '%s组php应用取消备用。。。。' % group, zone_code = zone_code, env_name = env_name,
              entrance_types = 'hosts', group = group)
    _rtn = doSwitch(env_name, zone_code, 'hosts', 'GNONE', None)
    log.info("app.modules.switch.resources.autoGNONE  %s组hosts切换GNONE,返回:%s" % (group, _rtn))
    if not _rtn['success'] or _rtn['data'] == 'OUT_OF_SERVICE':
        log.error("app.modules.switch.resources.autoGNONE  %s组hosts切换GNONE失败" % group)
        insertLog(log = '%s组php应用取消备用失败。。。。' % group, color = 'red', zone_code = zone_code, env_name = env_name,
                  entrance_types = 'hosts', group = group, show_error = "0")
        insertLog(log = '===============%s组取消备用失败==============' % group, br_count = 3, color = 'red',
                  zone_code = zone_code, env_name = env_name, group = group)
        return
    insertLog(log = '%s组php应用取消备用成功。。。。' % group, color = 'green', zone_code = zone_code, env_name = env_name,
              entrance_types = 'hosts', group = group)

    # 3、uSchedule启用A组任务

    insertLog(log = 'uSchedule启用%s组任务。。。。' % group, zone_code = zone_code, env_name = env_name,
              entrance_types = 'uschedule', group = group)
    _rtn = doSwitch(env_name, zone_code, 'uschedule', 'GNONE', None)
    log.info("app.modules.switch.resources.autoGNONE  %s组uschedule切换GNONE,返回:%s" % (group, _rtn))
    if not _rtn['success'] or _rtn['data'] == 'OUT_OF_SERVICE':
        log.error("app.modules.switch.resources.autoGNONE  %s组uschedule切换GNONE失败" % group)
        insertLog(log = 'uSchedule启用%s组任务失败。。。。' % group, color = 'red', zone_code = zone_code, env_name = env_name,
                  entrance_types = 'uschedule', group = group, show_error = "0")
        insertLog(log = '===============%s组取消备用失败==============' % group, br_count = 3, color = 'red',
                  zone_code = zone_code, env_name = env_name, group = group)
        return
    insertLog(log = 'uSchedule启用%s组任务成功。。。。' % group, color = 'green', zone_code = zone_code, env_name = env_name,
              entrance_types = 'uschedule', group = group)

    # 4、生产Haproxy启A

    insertLog(log = '生产Haproxy启用%s组。。。。' % group, zone_code = zone_code, env_name = env_name,
              entrance_types = 'haproxy', group = group)
    _rtn = doSwitch(env_name, zone_code, 'haproxy', 'GNONE', None)
    log.info("app.modules.switch.resources.autoGNONE  %s组haproxy切换GNONE,返回:%s" % (group, _rtn))
    if not _rtn['success'] or _rtn['data'] == 'OUT_OF_SERVICE':
        log.error("app.modules.switch.resources.autoGNONE  %s组haproxy切换GNONE失败" % group)
        insertLog(log = '生产Haproxy启用%s组失败。。。。' % group, color = 'red', zone_code = zone_code, env_name = env_name,
                  entrance_types = 'haproxy', group = group, show_error = "0")
        insertLog(log = '===============%s组取消备用失败==============' % group, br_count = 3, color = 'red',
                  zone_code = zone_code, env_name = env_name, group = group)
        return
    insertLog(log = '生产Haproxy启用%s组成功。。。。' % group, color = 'green', zone_code = zone_code, env_name = env_name,
              entrance_types = 'haproxy', group = group)
    insertLog(log = '===============%s组取消备用成功==============' % group, br_count = 3, color = 'green',
              zone_code = zone_code, env_name = env_name, entrance_types = 'uschedule', group = group)
    pass
